const vscode = require('vscode');
const path = require('path');
const fs = require('fs');
const util = require('./utils');

/**
 * 查找文件定义的provider，匹配到了就return一个location，否则不做处理
 * @param {*} document
 * @param {*} position
 * @param {*} token
 */
function provideDefinition(document, position, token) {
  
  // 获取工作目录
  const projectPath = util.getProjectPath(document);
  // 获取光标所在行的文档路径
  const { fileName } = document;
  // 获取光标所在行的文档夹路径
  const workDir = path.dirname(fileName);

  // 获取光标所在位置的双引号范围内的文本路径,并去除空格,引号，逗号
  let textPath = document.getText(document.getWordRangeAtPosition(position, /[\'\"](.*?)[\'\"]/g));
  textPath = textPath.replace(/,|\s|\'|\"/gi, '');
  // 获取光标所在行的信息
  const line = document.lineAt(position);
  

  // 如果跳转行存在import字样,屏蔽掉这个工具的跳转功能,因为会与开发编辑工具的跳转功能冲突
  if (line.text.includes('import')) return null;

  // wxml文件中微信标签上bindTap绑定方法跳转, 因为在wxml文件中,获取到的光标所在处的文本是整个文档,所以要修改
  // 光标所在行截取出来的字符串,没有.或/等路径符
  if (/\.wxml$/.test(fileName) && !/[\/\.]/.test(textPath)) {
    // const textLine = document.lineAt(position);
    // const wordRange = document.getWordRangeAtPosition(position, /[\w|\-]+\b/);
    // const tag = (line.text.match(/(?<=<\/?)[\w|\-]+\b/) || [])[0];
    // const word = document.getText(wordRange);
    // console.log(wordRange, word, tag, textPath);
   
    // 在wxml文件对应的js文件中,查找方法名所在的行号和列数
    const filePath = fileName.replace(/\.wxml$/, '.js');
    const pos = util.findStrInFile({ filePath, str: textPath});
    const { row, col } = pos;
    // 判断是否找到
    if (row != 0 && col != 0) {
      return new vscode.Location(vscode.Uri.file(filePath), new vscode.Position(row, col));
    }
    return [];
  }



  // 项目定制需求--ajax url跳转，不通用
  // 检测光标所在行的字符串中是否有ajax('')字样
  const ajaxReg1 = new RegExp(`ajax\\(\\s*.*('|")${textPath}('|"),?`, 'gm');
  //  检测光标所在行的字符串中是否有yield call(ajax字样
  const ajaxReg2 = new RegExp(`yield call\\(ajax\\, ?('|")${textPath}('|"), ?`, 'gm');
  const json = document.getText();
  if (ajaxReg1.test(json) || ajaxReg2.test(json)) {
    // webapp项目
    const destPath1 = `${projectPath}/src/config/api.js`;
    // 小程序项目
    const destPath2 = `${projectPath}/config/api-config.js`;
    let destPath = '';
    if (fs.existsSync(destPath1)) {
      destPath = destPath1;
    } else if (fs.existsSync(destPath2)) {
      destPath = destPath2;
    }
    // 文件存在
    if (fs.existsSync(destPath)) {
      try {
        // 查找关键字在文件中的行号和列号
        const pos = util.findStrInFile({ filePath:destPath, str: textPath });
        const { row, col } = pos;
        return new vscode.Location(vscode.Uri.file(destPath), new vscode.Position(row, col));
      } catch (error) {
        vscode.window.showErrorMessage('%c error:', 'color: #0e93e0;background: #aaefe5;', JSON.stringify(error));
        return [];
      }
    }
    return []
  }

  // 微信小程序app.json跳转逻辑比较特殊,存在分包路径，如果是分包路径,要拼接子包root路径部分
  if (fileName.includes('app.json')) {
    const json = JSON.parse(document.getText());
    // 分包路径判断
    let isSubPath = json.subpackages.some((item) => {
      if (item.pages.includes(textPath)) {
        // 如果是分包路径,则要拼接分包的root路径部分
        textPath = `/${item.root}/${textPath}`;
        return true;
      }
      return false;
    });
    // 如果是正常页面路径,要在页面路径前面加绝对路径符号/
    if (!isSubPath) {
      textPath = `/${textPath}`;
    }
  }

  // 如果没有文件后缀,说明是json,或者js,jsx文件中的navigateTo跳转,默认跳转到对应页面的wxml文件
  const reg = /\.\w+$/;
  let isNoSuffix = !reg.exec(textPath);
  // 没有文件后缀,添加默认的跳转文件类型
  if (isNoSuffix) {
    textPath = `${textPath}.wxml`;
  }

  let jumpPath;
  if (textPath.startsWith('/')) {
    // 为绝对路径时-直接拼接工程路径+截取的路径字符串
    jumpPath = path.join(projectPath, textPath);
  } else {
    // 为相对路径时-转换成绝对路径
    jumpPath = path.resolve(workDir, textPath);
  }

  console.log('====== 进入 provideDefinition 方法 ======');
  console.log('projectPath=%s ', projectPath); // 当前工程目录
  console.log('document:', document); // 文档对象
  console.log('position:', position); // 位置
  // console.log('token=%o', token); // 分词
  console.log('line:', line); // 当前光标所在行
  console.log('fileName=%s ', fileName); // 当前文件名
  console.log('workDir=%s', workDir); // 当前文件所在目录
  console.log('textPath=%s', textPath); // 跳转短路径
  console.log('jumpPath=%s ', jumpPath); // 跳转路径

  // 路径不存在则不跳转
  if (!jumpPath || !fs.existsSync(jumpPath)) {
    return null;
  } else {
    return new vscode.Location(vscode.Uri.file(jumpPath), new vscode.Position(0, 0));
  }
}

module.exports = function (context) {
  // 注册如何实现跳转到定义，第一个参数表示仅对js,jsx,ts,tsx,json,wxml文件生效
  context.subscriptions.push(
    vscode.languages.registerDefinitionProvider(
      { pattern: '**/*.{ts,js,jsx,tsx,json,wxml}' },
      {
        provideDefinition,
      }
    )
  );
};
